home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / unix / volume26 / cook-1.4 / part11 < prev    next >
Encoding:
Text File  |  1993-05-03  |  46.0 KB  |  2,261 lines

  1. Newsgroups: comp.sources.unix
  2. From: pmiller@bmr.gov.au (Peter Miller)
  3. Subject: v26i219: cook-1.4 - a file construction tool (like "make"), Part11/11
  4. Sender: unix-sources-moderator@efficacy.home.vix.com
  5. Approved: WhoAmI@efficacy.home.vix.com
  6.  
  7. Submitted-By: pmiller@bmr.gov.au (Peter Miller)
  8. Posting-Number: Volume 26, Issue 219
  9. Archive-Name: cook-1.4/part11
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 11 (of 11)."
  18. # Contents:  cook/builtin.c
  19. # Wrapped by vixie@efficacy.home.vix.com on Tue May  4 01:36:43 1993
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'cook/builtin.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'cook/builtin.c'\"
  23. else
  24. echo shar: Extracting \"'cook/builtin.c'\" \(43130 characters\)
  25. sed "s/^X//" >'cook/builtin.c' <<'END_OF_FILE'
  26. X/*
  27. X *    cook - file construction tool
  28. X *    Copyright (C) 1991, 1992, 1993 Peter Miller.
  29. X *    All rights reserved.
  30. X *
  31. X *    This program is free software; you can redistribute it and/or modify
  32. X *    it under the terms of the GNU General Public License as published by
  33. X *    the Free Software Foundation; either version 2 of the License, or
  34. X *    (at your option) any later version.
  35. X *
  36. X *    This program is distributed in the hope that it will be useful,
  37. X *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  38. X *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  39. X *    GNU General Public License for more details.
  40. X *
  41. X *    You should have received a copy of the GNU General Public License
  42. X *    along with this program; if not, write to the Free Software
  43. X *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  44. X *
  45. X * MANIFEST: functions to implement the builtin functions
  46. X *
  47. X * The builtin function all append their results to the supplied
  48. X * `result' word list.  The first word of the `args' word list
  49. X * is the name of the function.
  50. X *
  51. X * all of the functions return 0 in success, or -1 on error.
  52. X *
  53. X * Only a limited set of this are candidates for builtin functions,
  54. X * these are 
  55. X *    - string manipulation [dirname, stringset, ect ]
  56. X *    - environment manipulation [getenv(3), etc]
  57. X *    - stat(3) related functions [exists, mtime, pathname, etc]
  58. X *    - launching OS commands [execute, collect]
  59. X * The above list is though to be exhaustive.
  60. X *
  61. X * This explicitly and forever excluded from being a builtin function
  62. X * is anything which known or understands the format of some secific 
  63. X * class of files.
  64. X *
  65. X * Access to stdio(3) has been thought of, and explicitly avoided.
  66. X * Mostly because a specialist program used through [collect]
  67. X * will almost always be far faster.
  68. X */
  69. X
  70. X#include <stddef.h>
  71. X#include <stdlib.h>
  72. X#include <stdio.h>
  73. X#include <string.h>
  74. X#include <time.h>
  75. X#include <errno.h>
  76. X#include <sys/utsname.h>
  77. X
  78. X#include <builtin.h>
  79. X#include <cook.h>
  80. X#include <error.h>
  81. X#include <expr.h>
  82. X#include <glob.h>
  83. X#include <id.h>
  84. X#include <main.h>
  85. X#include <match.h>
  86. X#include <mem.h>
  87. X#include <option.h>
  88. X#include <os.h>
  89. X#include <word.h>
  90. X
  91. X
  92. Xtypedef struct func_ty func_ty;
  93. Xstruct func_ty
  94. X{
  95. X    char    *f_name;
  96. X    bifp    f_code;
  97. X};
  98. X
  99. X
  100. X/*
  101. X * NAME
  102. X *    func_if - conditional evaluation
  103. X *
  104. X * SYNOPSIS
  105. X *    int func_if(wlist *result, wlist *args);
  106. X *
  107. X * DESCRIPTION
  108. X *    Defined is a built-in function of if, described as follows:
  109. X *    This function requires one or more arguments.
  110. X *    The condition before the 'then' keyword is evaluated,
  111. X *    if true, the words between the 'then' and the 'else' are the result,
  112. X *    otherwise the words between the 'else' and the end are the value.
  113. X *    The else is optional.
  114. X *
  115. X * RETURNS
  116. X *    Appropriate things, see above.
  117. X *
  118. X * CAVEAT
  119. X *    The returned result is in dynamic memory.
  120. X *    It is the responsibility of the caller to dispose of
  121. X *    the result when it is finished, with a wl_free() call.
  122. X *
  123. X *    'then' and 'else' cant be escaped, sorry.
  124. X */
  125. X
  126. Xstatic int func_if _((wlist *, wlist *));
  127. X
  128. Xstatic int
  129. Xfunc_if(result, args)
  130. X    wlist        *result;
  131. X    wlist        *args;
  132. X{
  133. X    int        j;
  134. X    int        cond;
  135. X    static string_ty    *str_then;
  136. X    static string_ty    *str_else;
  137. X
  138. X    assert(result);
  139. X    assert(args);
  140. X    assert(args->wl_nwords);
  141. X    if (args->wl_nwords < 2)
  142. X    {
  143. X        expr_error
  144. X        (
  145. X            "%s: requires one or more arguments",
  146. X            args->wl_word[0]->str_text
  147. X        );
  148. X        return -1;
  149. X    }
  150. X    cond = 0;
  151. X    if (!str_then)
  152. X        str_then = str_from_c("then");
  153. X    if (!str_else)
  154. X        str_else = str_from_c("else");
  155. X    for
  156. X    (
  157. X        j = 1;
  158. X        j < args->wl_nwords && !str_equal(str_then, args->wl_word[j]);
  159. X        j++
  160. X    )
  161. X        cond |= str_bool(args->wl_word[j]);
  162. X    if (j >= args->wl_nwords)
  163. X    {
  164. X        expr_error("%s: no 'then' word", args->wl_word[0]->str_text);
  165. X        return -1;
  166. X    }
  167. X    j++;
  168. X    if (cond)
  169. X    {
  170. X        while
  171. X        (
  172. X            j < args->wl_nwords
  173. X        &&
  174. X            !str_equal(str_else, args->wl_word[j])
  175. X        )
  176. X        {
  177. X            wl_append(result, args->wl_word[j]);
  178. X            j++;
  179. X        }
  180. X    }
  181. X    else
  182. X    {
  183. X        while
  184. X        (
  185. X            j < args->wl_nwords
  186. X        &&
  187. X            !str_equal(str_else, args->wl_word[j])
  188. X        )
  189. X            j++;
  190. X        if (j < args->wl_nwords)
  191. X        {
  192. X            j++;
  193. X            while (j < args->wl_nwords)
  194. X            {
  195. X                wl_append(result, args->wl_word[j]);
  196. X                ++j;
  197. X            }
  198. X        }
  199. X    }
  200. X    return 0;
  201. X}
  202. X
  203. X
  204. X/*
  205. X * NAME
  206. X *    func_upcase - upcase strings
  207. X *
  208. X * SYNOPSIS
  209. X *    int func_upcase(wlist *result, wlist *args);
  210. X *
  211. X * DESCRIPTION
  212. X *    Defined is a built-in function of cook, described as follows:
  213. X *    This function requires one or more arguments,
  214. X *    which will bu upcased.
  215. X *
  216. X * RETURNS
  217. X *    It returns the arguments upcased.
  218. X *
  219. X * CAVEAT
  220. X *    The returned result is in dynamic memory.
  221. X *    It is the responsibility of the caller to dispose of
  222. X *    the result when it is finished, with a wl_free() call.
  223. X */
  224. X
  225. Xstatic int func_upcase _((wlist *, wlist *));
  226. X
  227. Xstatic int
  228. Xfunc_upcase(result, args)
  229. X    wlist        *result;
  230. X    wlist        *args;
  231. X{
  232. X    int        j;
  233. X
  234. X    assert(result);
  235. X    assert(args);
  236. X    assert(args->wl_nwords);
  237. X    if (args->wl_nwords < 2)
  238. X    {
  239. X        expr_error
  240. X        (
  241. X            "%s: requires one or more arguments",
  242. X            args->wl_word[0]->str_text
  243. X        );
  244. X        return -1;
  245. X    }
  246. X    for (j = 1; j < args->wl_nwords; j++)
  247. X    {
  248. X        string_ty *s;
  249. X
  250. X        s = str_upcase(args->wl_word[j]);
  251. X        wl_append(result, s);
  252. X        str_free(s);
  253. X    }
  254. X    return 0;
  255. X}
  256. X
  257. X
  258. X/*
  259. X * NAME
  260. X *    func_downcase - downcase strings
  261. X *
  262. X * SYNOPSIS
  263. X *    int func_downcase(wlist *result, wlist *args);
  264. X *
  265. X * DESCRIPTION
  266. X *    Defined is a built-in function of cook, described as follows:
  267. X *    This function requires one or more arguments,
  268. X *    which will bu downcased.
  269. X *
  270. X * RETURNS
  271. X *    It returns the arguments downcased.
  272. X *
  273. X * CAVEAT
  274. X *    The returned result is in dynamic memory.
  275. X *    It is the responsibility of the caller to dispose of
  276. X *    the result when it is finished, with a wl_free() call.
  277. X */
  278. X
  279. Xstatic int func_downcase _((wlist *, wlist *));
  280. X
  281. Xstatic int
  282. Xfunc_downcase(result, args)
  283. X    wlist        *result;
  284. X    wlist        *args;
  285. X{
  286. X    int        j;
  287. X
  288. X    assert(result);
  289. X    assert(args);
  290. X    assert(args->wl_nwords);
  291. X    if (args->wl_nwords < 2)
  292. X    {
  293. X        expr_error
  294. X        (
  295. X            "%s: requires one or more arguments",
  296. X            args->wl_word[0]->str_text
  297. X        );
  298. X        return -1;
  299. X    }
  300. X    for (j = 1; j < args->wl_nwords; j++)
  301. X    {
  302. X        string_ty    *s;
  303. X
  304. X        s = str_downcase(args->wl_word[j]);
  305. X        wl_append(result, s);
  306. X        str_free(s);
  307. X    }
  308. X    return 0;
  309. X}
  310. X
  311. X
  312. X/*
  313. X * NAME
  314. X *    func_dir - dir part
  315. X *
  316. X * SYNOPSIS
  317. X *    int func_dir(wlist *result, wlist *args);
  318. X *
  319. X * DESCRIPTION
  320. X *    "dir" is a built-in function of cook, described as follows:
  321. X *    This function requires one or more arguments,
  322. X *    the name of a files of which to get the dir parts.
  323. X *
  324. X * RETURNS
  325. X *    It returns a string containing the directory parts
  326. X *    of the named files.
  327. X *
  328. X * CAVEAT
  329. X *    The returned result is in dynamic memory.
  330. X *    It is the responsibility of the caller to dispose of
  331. X *    the result when it is finished, with a wl_free() call.
  332. X */
  333. X
  334. Xstatic int func_dir _((wlist *, wlist *));
  335. X
  336. Xstatic int
  337. Xfunc_dir(result, args)
  338. X    wlist        *result;
  339. X    wlist        *args;
  340. X{
  341. X    int        j;
  342. X
  343. X    assert(result);
  344. X    assert(args);
  345. X    assert(args->wl_nwords);
  346. X    if (args->wl_nwords < 2)
  347. X    {
  348. X        expr_error
  349. X        (
  350. X            "%s: requires one or more arguments",
  351. X            args->wl_word[0]->str_text
  352. X        );
  353. X        return -1;
  354. X    }
  355. X    for (j = 1; j < args->wl_nwords; j++)
  356. X    {
  357. X        string_ty    *s;
  358. X
  359. X        s = os_dirname(args->wl_word[j]);
  360. X        if (!s)
  361. X            return -1;
  362. X        wl_append(result, s);
  363. X        str_free(s);
  364. X    }
  365. X    return 0;
  366. X}
  367. X
  368. X
  369. X/*
  370. X * NAME
  371. X *    func_entryname - entryname part
  372. X *
  373. X * SYNOPSIS
  374. X *    int func_entryname(wlist *result, wlist *args);
  375. X *
  376. X * DESCRIPTION
  377. X *    Defined is a built-in function of cook, described as follows:
  378. X *    This function requires one or more arguments,
  379. X *    the name of a files of which to get the entryname parts.
  380. X *
  381. X * RETURNS
  382. X *    It returns a string containing the entryname parts
  383. X *    of the named files.
  384. X *
  385. X * CAVEAT
  386. X *    The returned result is in dynamic memory.
  387. X *    It is the responsibility of the caller to dispose of
  388. X *    the result when it is finished, with a wl_free() call.
  389. X */
  390. X
  391. Xstatic int func_entryname _((wlist *, wlist *));
  392. X
  393. Xstatic int
  394. Xfunc_entryname(result, args)
  395. X    wlist        *result;
  396. X    wlist        *args;
  397. X{
  398. X    int        j;
  399. X
  400. X    assert(result);
  401. X    assert(args);
  402. X    assert(args->wl_nwords);
  403. X    if (args->wl_nwords < 2)
  404. X    {
  405. X        expr_error
  406. X        (
  407. X            "%s: requires one or more arguments",
  408. X            args->wl_word[0]->str_text
  409. X        );
  410. X        return -1;
  411. X    }
  412. X    for (j = 1; j < args->wl_nwords; j++)
  413. X    {
  414. X        string_ty    *s;
  415. X
  416. X        s = os_entryname(args->wl_word[j]);
  417. X        if (!s)
  418. X            return -1;
  419. X        wl_append(result, s);
  420. X        str_free(s);
  421. X    }
  422. X    return 0;
  423. X}
  424. X
  425. X
  426. X/*
  427. X * NAME
  428. X *    func_pathname - pathname part
  429. X *
  430. X * SYNOPSIS
  431. X *    int func_pathname(wlist *result, wlist *args);
  432. X *
  433. X * DESCRIPTION
  434. X *    Defined is a built-in function of cook, described as follows:
  435. X *    This function requires one or more arguments,
  436. X *    the name of a files of which to get the pathname parts.
  437. X *
  438. X * RETURNS
  439. X *    It returns a string containing the pathname parts
  440. X *    of the named files.
  441. X *
  442. X * CAVEAT
  443. X *    The returned result is in dynamic memory.
  444. X *    It is the responsibility of the caller to dispose of
  445. X *    the result when it is finished, with a wl_free() call.
  446. X */
  447. X
  448. Xstatic int func_pathname _((wlist *, wlist *));
  449. X
  450. Xstatic int
  451. Xfunc_pathname(result, args)
  452. X    wlist        *result;
  453. X    wlist        *args;
  454. X{
  455. X    int        j;
  456. X
  457. X    assert(result);
  458. X    assert(args);
  459. X    assert(args->wl_nwords);
  460. X    if (args->wl_nwords < 2)
  461. X    {
  462. X        expr_error
  463. X        (
  464. X            "%s: requires one or more arguments",
  465. X            args->wl_word[0]->str_text
  466. X        );
  467. X        return -1;
  468. X    }
  469. X    for (j = 1; j < args->wl_nwords; j++)
  470. X    {
  471. X        string_ty    *s;
  472. X
  473. X        s = os_pathname(args->wl_word[j]);
  474. X        if (!s)
  475. X            return -1;
  476. X        wl_append(result, s);
  477. X        str_free(s);
  478. X    }
  479. X    return 0;
  480. X}
  481. X
  482. X
  483. X/*
  484. X * NAME
  485. X *    func_mtime - file last modified time
  486. X *
  487. X * SYNOPSIS
  488. X *    int func_mtime(wlist *result, wlist *args);
  489. X *
  490. X * DESCRIPTION
  491. X *    Defined is a built-in function of cook, described as follows:
  492. X *    This function requires a single argument,
  493. X *    the name of a file of which to get the last modified time.
  494. X *
  495. X * RETURNS
  496. X *    It returns a string containing the last modified time
  497. X *    (suitable for comparing with others) of the named file,
  498. X *    and "" (false) if the files does not exist
  499. X *
  500. X * CAVEAT
  501. X *    The returned result is in dynamic memory.
  502. X *    It is the responsibility of the caller to dispose of
  503. X *    the result when it is finished, with a wl_free() call.
  504. X */
  505. X
  506. Xstatic int func_mtime _((wlist *, wlist *));
  507. X
  508. Xstatic int
  509. Xfunc_mtime(result, args)
  510. X    wlist        *result;
  511. X    wlist        *args;
  512. X{
  513. X    int        j;
  514. X
  515. X    assert(result);
  516. X    assert(args);
  517. X    assert(args->wl_nwords);
  518. X    if (args->wl_nwords < 2)
  519. X    {
  520. X        expr_error
  521. X        (
  522. X            "%s: requires one or more arguments",
  523. X            args->wl_word[0]->str_text
  524. X        );
  525. X        return -1;
  526. X    }
  527. X    for (j = 1; j < args->wl_nwords; j++)
  528. X    {
  529. X        time_t        mtime;
  530. X
  531. X        mtime = os_mtime(args->wl_word[j]);
  532. X        if (mtime < 0)
  533. X            return -1;
  534. X        if (mtime == 0)
  535. X            wl_append(result, str_false);
  536. X        else
  537. X        {
  538. X            struct tm    *tm;
  539. X            string_ty    *s;
  540. X
  541. X            tm = localtime(&mtime);
  542. X            s =
  543. X                str_format
  544. X                (
  545. X                    "%02d%02d%02d%02d%02d%02d",
  546. X                    tm->tm_year,
  547. X                    tm->tm_mon+1,
  548. X                    tm->tm_mday,
  549. X                    tm->tm_hour,
  550. X                    tm->tm_min,
  551. X                    tm->tm_sec
  552. X                );
  553. X            wl_append(result, s);
  554. X            str_free(s);
  555. X        }
  556. X    }
  557. X    return 0;
  558. X}
  559. X
  560. X
  561. X/*
  562. X * NAME
  563. X *    func_prepost - add prefix and suffix
  564. X *
  565. X * SYNOPSIS
  566. X *    int func_prepost(wlist *result, wlist *args);
  567. X *
  568. X * DESCRIPTION
  569. X *    Prepost is a built-in function of cook, described as follows:
  570. X *    This function must have at least two arguments.
  571. X *    The first argument is a prefix and the second argument is a suffix.
  572. X *
  573. X * RETURNS
  574. X *    The resulting word list is the third and later arguments each given
  575. X *    the prefix and suffix as defined by the first and second arguments.
  576. X *
  577. X * CAVEAT
  578. X *    The returned result is in dynamic memory.
  579. X *    It is the responsibility of the caller to dispose of
  580. X *    the result when it is finished, with a wl_free() call.
  581. X */
  582. X
  583. Xstatic int func_prepost _((wlist *, wlist *));
  584. X
  585. Xstatic int
  586. Xfunc_prepost(result, args)
  587. X    wlist        *result;
  588. X    wlist        *args;
  589. X{
  590. X    int        j;
  591. X
  592. X    assert(result);
  593. X    assert(args);
  594. X    assert(args->wl_nwords);
  595. X    if (args->wl_nwords < 3)
  596. X    {
  597. X        expr_error
  598. X        (
  599. X            "%s: requires at least two arguments",
  600. X            args->wl_word[0]->str_text
  601. X        );
  602. X        return -1;
  603. X    }
  604. X    for (j = 3; j < args->wl_nwords; j++)
  605. X    {
  606. X        string_ty    *s;
  607. X
  608. X        s =
  609. X            str_cat_three
  610. X            (
  611. X                args->wl_word[1],
  612. X                args->wl_word[j],
  613. X                args->wl_word[2]
  614. X            );
  615. X        wl_append(result, s);
  616. X        str_free(s);
  617. X    }
  618. X    return 0;
  619. X}
  620. X
  621. X
  622. X/*
  623. X * NAME
  624. X *    func_defined - is a variable defined
  625. X *
  626. X * SYNOPSIS
  627. X *    int func_defined(wlist *result, wlist *args);
  628. X *
  629. X * DESCRIPTION
  630. X *    Defined is a built-in function of cook, described as follows:
  631. X *    This function requires a single argument,
  632. X *    the name of a variable to be tested for existence.
  633. X *
  634. X * RETURNS
  635. X *    It returns "1" (true) if the named variable is defined
  636. X *    and "" (false) if it is not.
  637. X *
  638. X * CAVEAT
  639. X *    The returned result is in dynamic memory.
  640. X *    It is the responsibility of the caller to dispose of
  641. X *    the result when it is finished, with a wl_free() call.
  642. X */
  643. X
  644. Xstatic int func_defined _((wlist *, wlist *));
  645. X
  646. Xstatic int
  647. Xfunc_defined(result, args)
  648. X    wlist        *result;
  649. X    wlist        *args;
  650. X{
  651. X    int        j;
  652. X
  653. X    assert(result);
  654. X    assert(args);
  655. X    assert(args->wl_nwords);
  656. X    if (args->wl_nwords < 2)
  657. X    {
  658. X        expr_error
  659. X        (
  660. X            "%s: requires one or more arguments",
  661. X            args->wl_word[0]->str_text
  662. X        );
  663. X        return -1;
  664. X    }
  665. X    for (j = 1; j < args->wl_nwords; j++)
  666. X    {
  667. X        wlist        value;
  668. X
  669. X        if (id_search(args->wl_word[j], ID_CLASS_VARIABLE, &value))
  670. X        {
  671. X            wl_free(&value);
  672. X            wl_append(result, str_true);
  673. X        }
  674. X        else
  675. X            wl_append(result, str_false);
  676. X    }
  677. X    return 0;
  678. X}
  679. X
  680. X
  681. X/*
  682. X * NAME
  683. X *    func_not - logical negation
  684. X *
  685. X * SYNOPSIS
  686. X *    int func_not(wlist *result, wlist *args);
  687. X *
  688. X * DESCRIPTION
  689. X *    Not is a built-in function of cook, described as follows:
  690. X *    This function requires zero or more arguments,
  691. X *    the value to be logically negated.
  692. X *
  693. X * RETURNS
  694. X *    It returns "1" (true) if all of the arguments are "" (false), or there
  695. X *    are no arguments; and returns "" (false) otherwise.
  696. X *
  697. X * CAVEAT
  698. X *    The returned result is in dynamic memory.
  699. X *    It is the responsibility of the caller to dispose of
  700. X *    the result when it is finished, with a wl_free() call.
  701. X */
  702. X
  703. Xstatic int func_not _((wlist *, wlist *));
  704. X
  705. Xstatic int
  706. Xfunc_not(result, args)
  707. X    wlist        *result;
  708. X    wlist        *args;
  709. X{
  710. X    int        j;
  711. X
  712. X    assert(result);
  713. X    assert(args);
  714. X    assert(args->wl_nwords);
  715. X    for (j = 1; j < args->wl_nwords; j++)
  716. X    {
  717. X        if (str_bool(args->wl_word[j]))
  718. X        {
  719. X            wl_append(result, str_false);
  720. X            return 0;
  721. X        }
  722. X    }
  723. X    wl_append(result, str_true);
  724. X    return 0;
  725. X}
  726. X
  727. X
  728. X/*
  729. X * NAME
  730. X *    func_and - logical conjunction
  731. X *
  732. X * SYNOPSIS
  733. X *    int func_and(wlist *result, wlist *args);
  734. X *
  735. X * DESCRIPTION
  736. X *    And is a built-in function of cook, described as follows:
  737. X *    This function requires at least two arguments,
  738. X *    upon which it forms a logical conjunction.
  739. X *
  740. X * RETURNS
  741. X *    The value returned is "1" (true) if none of the arguments
  742. X *    are "" (false), otherwise "" (false) is returned.
  743. X *
  744. X * CAVEAT
  745. X *    The returned result is in dynamic memory.
  746. X *    It is the responsibility of the caller to dispose of
  747. X *    the result when it is finished, with a wl_free() call.
  748. X */
  749. X
  750. Xstatic int func_and _((wlist *, wlist *));
  751. X
  752. Xstatic int
  753. Xfunc_and(result, args)
  754. X    wlist        *result;
  755. X    wlist        *args;
  756. X{
  757. X    int        j;
  758. X
  759. X    assert(result);
  760. X    assert(args);
  761. X    assert(args->wl_nwords);
  762. X    if (args->wl_nwords < 3)
  763. X    {
  764. X        expr_error
  765. X        (
  766. X            "%s: requires at least two arguments",
  767. X            args->wl_word[0]->str_text
  768. X        );
  769. X        return -1;
  770. X    }
  771. X    for (j = 1; j < args->wl_nwords; j++)
  772. X    {
  773. X        if (!str_bool(args->wl_word[j]))
  774. X        {
  775. X            wl_append(result, str_false);
  776. X            return 0;
  777. X        }
  778. X    }
  779. X    wl_append(result, str_true);
  780. X    return 0;
  781. X}
  782. X
  783. X
  784. X/*
  785. X * NAME
  786. X *    func_or - logical disjunction
  787. X *
  788. X * SYNOPSIS
  789. X *    int func_or(wlist *result, wlist *args);
  790. X *
  791. X * DESCRIPTION
  792. X *    Or is a built-in function of cook, described as follows:
  793. X *    This function requires at least two arguments,
  794. X *    upon which it forms a logical disjunction.
  795. X *
  796. X * RETURNS
  797. X *    The value returned is "1" (true) if any one of the arguments is
  798. X *    not "" (false), otherwise "" (false) is returned.
  799. X *
  800. X * CAVEAT
  801. X *    The returned result is in dynamic memory.
  802. X *    It is the responsibility of the caller to dispose of
  803. X *    the result when it is finished, with a wl_free() call.
  804. X */
  805. X
  806. Xstatic int func_or _((wlist *, wlist *));
  807. X
  808. Xstatic int
  809. Xfunc_or(result, args)
  810. X    wlist        *result;
  811. X    wlist        *args;
  812. X{
  813. X    int        j;
  814. X
  815. X    assert(result);
  816. X    assert(args);
  817. X    assert(args->wl_nwords);
  818. X    if (args->wl_nwords < 3)
  819. X    {
  820. X        expr_error
  821. X        (
  822. X            "%s: requires at least two arguments",
  823. X            args->wl_word[0]->str_text
  824. X        );
  825. X        return -1;
  826. X    }
  827. X    for (j = 1; j < args->wl_nwords; j++)
  828. X    {
  829. X        if (str_bool(args->wl_word[j]))
  830. X        {
  831. X            wl_append(result, str_true);
  832. X            return 0;
  833. X        }
  834. X    }
  835. X    wl_append(result, str_false);
  836. X    return 0;
  837. X}
  838. X
  839. X
  840. X/*
  841. X * NAME
  842. X *    func_exec - execute a command
  843. X *
  844. X * SYNOPSIS
  845. X *    int func_exec(wlist *result, wlist *args);
  846. X *
  847. X * DESCRIPTION
  848. X *    Exec is a built-in function of cook, described as follows:
  849. X *    This function requires at least one argument, and
  850. X *    executes the command given by the arguments.
  851. X *
  852. X * RETURNS
  853. X *    If the executed command returns an error code the resulting value
  854. X *    is "" (false), otherwise it is "1" (true).
  855. X *
  856. X * CAVEAT
  857. X *    The returned result is in dynamic memory.
  858. X *    It is the responsibility of the caller to dispose of
  859. X *    the result when it is finished, with a wl_free() call.
  860. X */
  861. X
  862. Xstatic int func_exec _((wlist *, wlist *));
  863. X
  864. Xstatic int
  865. Xfunc_exec(result, args)
  866. X    wlist        *result;
  867. X    wlist        *args;
  868. X{
  869. X    wlist        wl;
  870. X    int        j;
  871. X    string_ty    *s;
  872. X
  873. X    assert(result);
  874. X    assert(args);
  875. X    assert(args->wl_nwords);
  876. X    if (args->wl_nwords < 2)
  877. X    {
  878. X        expr_error
  879. X        (
  880. X            "%s: requires at least one argument",
  881. X            args->wl_word[0]->str_text
  882. X        );
  883. X        return -1;
  884. X    }
  885. X    wl_zero(&wl);
  886. X    for (j = 1; j < args->wl_nwords; j++)
  887. X        wl_append(&wl, args->wl_word[j]);
  888. X    j = os_execute(&wl, (string_ty *)0);
  889. X    wl_free(&wl);
  890. X    if (j < 0)
  891. X        return -1;
  892. X    s = (j ? str_false : str_true);
  893. X    wl_append(result, s);
  894. X    return 0;
  895. X}
  896. X
  897. X
  898. X/*
  899. X * NAME
  900. X *    func_match - wildcard mapping
  901. X *
  902. X * SYNOPSIS
  903. X *    int func_match(wlist *result, wlist *args);
  904. X *
  905. X * DESCRIPTION
  906. X *    Fromto is a built-in function of cook, described as follows:
  907. X *    This function requires at least two arguments.
  908. X *    Fromto gives the user access to the wildcard transformations
  909. X *    available to cook.
  910. X *    The first argument is the "from" form,
  911. X *    the second argument is the "to" form.
  912. X *
  913. X * RETURNS
  914. X *    All other arguments are mapped from one to the other.
  915. X *
  916. X * CAVEAT
  917. X *    The returned result is in dynamic memory.
  918. X *    It is the responsibility of the caller to dispose of
  919. X *    the result when it is finished, with a wl_free() call.
  920. X */
  921. X
  922. Xstatic int func_match _((wlist *, wlist *));
  923. X
  924. Xstatic int
  925. Xfunc_match(result, args)
  926. X    wlist        *result;
  927. X    wlist        *args;
  928. X{
  929. X    int        j;
  930. X    match_ty    *field;
  931. X
  932. X    assert(result);
  933. X    assert(args);
  934. X    assert(args->wl_nwords);
  935. X    if (args->wl_nwords < 2)
  936. X    {
  937. X        expr_error
  938. X        (
  939. X            "%s: requires one or more arguments",
  940. X            args->wl_word[0]->str_text
  941. X        );
  942. X        return -1;
  943. X    }
  944. X    for (j = 2; j < args->wl_nwords; j++)
  945. X    {
  946. X        field = match(args->wl_word[1], args->wl_word[j]);
  947. X        if (field)
  948. X        {
  949. X            wl_append(result, str_true);
  950. X            match_free(field);
  951. X        }
  952. X        else
  953. X            wl_append(result, str_false);
  954. X    }
  955. X    return 0;
  956. X}
  957. X
  958. X
  959. X/*
  960. X * NAME
  961. X *    func_match - wildcard mapping
  962. X *
  963. X * SYNOPSIS
  964. X *    int func_match(wlist *result, wlist *args);
  965. X *
  966. X * DESCRIPTION
  967. X *    Fromto is a built-in function of cook, described as follows:
  968. X *    This function requires at least two arguments.
  969. X *    Fromto gives the user access to the wildcard transformations
  970. X *    available to cook.
  971. X *    The first argument is the "from" form,
  972. X *    the second argument is the "to" form.
  973. X *
  974. X * RETURNS
  975. X *    All other arguments are mapped from one to the other.
  976. X *
  977. X * CAVEAT
  978. X *    The returned result is in dynamic memory.
  979. X *    It is the responsibility of the caller to dispose of
  980. X *    the result when it is finished, with a wl_free() call.
  981. X */
  982. X
  983. Xstatic int func_match_mask _((wlist *, wlist *));
  984. X
  985. Xstatic int
  986. Xfunc_match_mask(result, args)
  987. X    wlist        *result;
  988. X    wlist        *args;
  989. X{
  990. X    int        j;
  991. X    match_ty    *field;
  992. X
  993. X    assert(result);
  994. X    assert(args);
  995. X    assert(args->wl_nwords);
  996. X    if (args->wl_nwords < 2)
  997. X    {
  998. X        expr_error
  999. X        (
  1000. X            "%s: requires one or more arguments",
  1001. X            args->wl_word[0]->str_text
  1002. X        );
  1003. X        return -1;
  1004. X    }
  1005. X    for (j = 2; j < args->wl_nwords; j++)
  1006. X    {
  1007. X        field = match(args->wl_word[1], args->wl_word[j]);
  1008. X        if (field)
  1009. X        {
  1010. X            wl_append(result, args->wl_word[j]);
  1011. X            match_free(field);
  1012. X        }
  1013. X    }
  1014. X    return 0;
  1015. X}
  1016. X
  1017. X
  1018. X/*
  1019. X * NAME
  1020. X *    func_fromto - wildcard mapping
  1021. X *
  1022. X * SYNOPSIS
  1023. X *    int func_fromto(wlist *result, wlist *args);
  1024. X *
  1025. X * DESCRIPTION
  1026. X *    Fromto is a built-in function of cook, described as follows:
  1027. X *    This function requires at least two arguments.
  1028. X *    Fromto gives the user access to the wildcard transformations
  1029. X *    available to cook.
  1030. X *    The first argument is the "from" form,
  1031. X *    the second argument is the "to" form.
  1032. X *
  1033. X * RETURNS
  1034. X *    All other arguments are mapped from one to the other.
  1035. X *
  1036. X * CAVEAT
  1037. X *    The returned result is in dynamic memory.
  1038. X *    It is the responsibility of the caller to dispose of
  1039. X *    the result when it is finished, with a wl_free() call.
  1040. X */
  1041. X
  1042. Xstatic int func_fromto _((wlist *, wlist *));
  1043. X
  1044. Xstatic int
  1045. Xfunc_fromto(result, args)
  1046. X    wlist        *result;
  1047. X    wlist        *args;
  1048. X{
  1049. X    int        j;
  1050. X    match_ty    *field;
  1051. X
  1052. X    assert(result);
  1053. X    assert(args);
  1054. X    assert(args->wl_nwords);
  1055. X    if (args->wl_nwords < 3)
  1056. X    {
  1057. X        expr_error
  1058. X        (
  1059. X            "%s: requires at least two arguments",
  1060. X            args->wl_word[0]->str_text
  1061. X        );
  1062. X        return -1;
  1063. X    }
  1064. X    for (j = 3; j < args->wl_nwords; j++)
  1065. X    {
  1066. X        field = match(args->wl_word[1], args->wl_word[j]);
  1067. X        if (field)
  1068. X        {
  1069. X            string_ty    *s;
  1070. X
  1071. X            s = reconstruct(args->wl_word[2], field);
  1072. X            wl_append(result, s);
  1073. X            str_free(s);
  1074. X            match_free(field);
  1075. X        }
  1076. X        else
  1077. X            wl_append(result, args->wl_word[j]);
  1078. X    }
  1079. X    return 0;
  1080. X}
  1081. X
  1082. X
  1083. X/*
  1084. X * NAME
  1085. X *    func_head - head of a wordlist
  1086. X *
  1087. X * SYNOPSIS
  1088. X *    int func_fromto(wlist *result, wlist *args);
  1089. X *
  1090. X * DESCRIPTION
  1091. X *    Head is a built-in function of cook, described as follows:
  1092. X *    This function requires zero or more arguments.
  1093. X *
  1094. X * RETURNS
  1095. X *    The wordlist returned is empty if there were no arguemnts,
  1096. X *    or the first argument if there were arguments.
  1097. X *
  1098. X * CAVEAT
  1099. X *    The returned result is in dynamic memory.
  1100. X *    It is the responsibility of the caller to dispose of
  1101. X *    the result when it is finished, with a wl_free() call.
  1102. X */
  1103. X
  1104. Xstatic int func_head _((wlist *, wlist *));
  1105. X
  1106. Xstatic int
  1107. Xfunc_head(result, args)
  1108. X    wlist        *result;
  1109. X    wlist        *args;
  1110. X{
  1111. X    assert(result);
  1112. X    assert(args);
  1113. X    assert(args->wl_nwords);
  1114. X    if (args->wl_nwords >= 2)
  1115. X        wl_append(result, args->wl_word[1]);
  1116. X    return 0;
  1117. X}
  1118. X
  1119. X
  1120. X/*
  1121. X * NAME
  1122. X *    func_tail - tail of a wordlist
  1123. X *
  1124. X * SYNOPSIS
  1125. X *    int func_tail(wlist *result, wlist *args);
  1126. X *
  1127. X * DESCRIPTION
  1128. X *    Tail is a built-in function of cook, described as follows:
  1129. X *    This function requires zero or more arguments.
  1130. X *
  1131. X * RETURNS
  1132. X *    The word list returned will be empty if
  1133. X *    there is less than two arguemnts,
  1134. X *    otherwise it will consist of the second and later arguments.
  1135. X *
  1136. X * CAVEAT
  1137. X *    The returned result is in dynamic memory.
  1138. X *    It is the responsibility of the caller to dispose of
  1139. X *    the result when it is finished, with a wl_free() call.
  1140. X */
  1141. X
  1142. Xstatic int func_tail _((wlist *, wlist *));
  1143. X
  1144. Xstatic int
  1145. Xfunc_tail(result, args)
  1146. X    wlist        *result;
  1147. X    wlist        *args;
  1148. X{
  1149. X    int        j;
  1150. X
  1151. X    assert(result);
  1152. X    assert(args);
  1153. X    assert(args->wl_nwords);
  1154. X    for (j = 2; j < args->wl_nwords; j++)
  1155. X        wl_append(result, args->wl_word[j]);
  1156. X    return 0;
  1157. X}
  1158. X
  1159. X
  1160. X/*
  1161. X * NAME
  1162. X *    func_catenate - catenate a wordlist
  1163. X *
  1164. X * SYNOPSIS
  1165. X *    int func_catenate(wlist *result, wlist *args);
  1166. X *
  1167. X * DESCRIPTION
  1168. X *    Catenate is a built-in function of cook, described as follows:
  1169. X *    This function requires zero or more arguments.
  1170. X *
  1171. X * RETURNS
  1172. X *    A word list containg zero words if there were no arguments,
  1173. X *    or a single word which is the catenation of the arguments.
  1174. X *
  1175. X * CAVEAT
  1176. X *    The returned result is in dynamic memory.
  1177. X *    It is the responsibility of the caller to dispose of
  1178. X *    the result when it is finished, with a wl_free() call.
  1179. X */
  1180. X
  1181. Xstatic int func_catenate _((wlist *, wlist *));
  1182. X
  1183. Xstatic int
  1184. Xfunc_catenate(result, args)
  1185. X    wlist        *result;
  1186. X    wlist        *args;
  1187. X{
  1188. X    int        j;
  1189. X    static char    *tmp;
  1190. X    static size_t    tmplen;
  1191. X    size_t        length;
  1192. X    char        *pos;
  1193. X    string_ty    *s;
  1194. X
  1195. X    assert(result);
  1196. X    assert(args);
  1197. X    assert(args->wl_nwords);
  1198. X    if (args->wl_nwords < 2)
  1199. X        return 0;
  1200. X    if (args->wl_nwords == 2)
  1201. X    {
  1202. X        wl_append(result, args->wl_word[1]);
  1203. X        return 0;
  1204. X    }
  1205. X
  1206. X    length = 0;
  1207. X    for (j = 1; j < args->wl_nwords; j++)
  1208. X        length += args->wl_word[j]->str_length;
  1209. X    if (!tmp)
  1210. X    {
  1211. X        tmplen = length;
  1212. X        if (tmplen < 16)
  1213. X            tmplen = 16;
  1214. X        tmp = mem_alloc(tmplen);
  1215. X    }
  1216. X    else
  1217. X    {
  1218. X        if (tmplen < length)
  1219. X        {
  1220. X            tmplen = length;
  1221. X            mem_change_size(&tmp, tmplen);
  1222. X        }
  1223. X    }
  1224. X    pos = tmp;
  1225. X    for (j = 1; j < args->wl_nwords; j++)
  1226. X    {
  1227. X        s = args->wl_word[j];
  1228. X        memcpy(pos, s->str_text, s->str_length);
  1229. X        pos += s->str_length;
  1230. X    }
  1231. X    s = str_n_from_c(tmp, length);
  1232. X    wl_append(result, s);
  1233. X    str_free(s);
  1234. X    return 0;
  1235. X}
  1236. X
  1237. X
  1238. X/*
  1239. X * NAME
  1240. X *    func_count - length of a word list
  1241. X *
  1242. X * SYNOPSIS
  1243. X *    int func_count(wlist *result, wlist *args);
  1244. X *
  1245. X * DESCRIPTION
  1246. X *    Count is a built-in function of cook, described as follows:
  1247. X *    This function requires zero or more arguments.
  1248. X *
  1249. X * RETURNS
  1250. X *    A word list containg a single word containing the (decimal)
  1251. X *    length of the argument list.
  1252. X *
  1253. X * CAVEAT
  1254. X *    The returned result is in dynamic memory.
  1255. X *    It is the responsibility of the caller to dispose of
  1256. X *    the result when it is finished, with a wl_free() call.
  1257. X */
  1258. X
  1259. Xstatic int func_count _((wlist *, wlist *));
  1260. X
  1261. Xstatic int
  1262. Xfunc_count(result, args)
  1263. X    wlist        *result;
  1264. X    wlist        *args;
  1265. X{
  1266. X    string_ty    *s;
  1267. X
  1268. X    assert(result);
  1269. X    assert(args);
  1270. X    assert(args->wl_nwords);
  1271. X    s = str_format("%ld", args->wl_nwords - 1);
  1272. X    wl_append(result, s);
  1273. X    str_free(s);
  1274. X    return 0;
  1275. X}
  1276. X
  1277. X
  1278. X/*
  1279. X * NAME
  1280. X *    func_in - test for set membership
  1281. X *
  1282. X * SYNOPSIS
  1283. X *    int func_in(wlist *result, wlist *args);
  1284. X *
  1285. X * DESCRIPTION
  1286. X *    In is a built-in function of cook, described as follows:
  1287. X *    This function requires one or more arguments.
  1288. X *
  1289. X * RETURNS
  1290. X *    A word list containg a single word: "1" (true) if the first argument
  1291. X *    is the same as any of the later ones; "" (false) if not.
  1292. X *
  1293. X * CAVEAT
  1294. X *    The returned result is in dynamic memory.
  1295. X *    It is the responsibility of the caller to dispose of
  1296. X *    the result when it is finished, with a wl_free() call.
  1297. X */
  1298. X
  1299. Xstatic int func_in _((wlist *, wlist *));
  1300. X
  1301. Xstatic int
  1302. Xfunc_in(result, args)
  1303. X    wlist        *result;
  1304. X    wlist        *args;
  1305. X{
  1306. X    int        j;
  1307. X
  1308. X    assert(result);
  1309. X    assert(args);
  1310. X    assert(args->wl_nwords);
  1311. X    if (args->wl_nwords < 2)
  1312. X    {
  1313. X        expr_error
  1314. X        (
  1315. X            "%s: requires one or more arguments",
  1316. X            args->wl_word[0]->str_text
  1317. X        );
  1318. X        return -1;
  1319. X    }
  1320. X    for (j = 2; j < args->wl_nwords; j++)
  1321. X    {
  1322. X        if (str_equal(args->wl_word[1], args->wl_word[j]))
  1323. X        {
  1324. X            wl_append(result, str_true);
  1325. X            return 0;
  1326. X        }
  1327. X    }
  1328. X    wl_append(result, str_false);
  1329. X    return 0;
  1330. X}
  1331. X
  1332. X
  1333. X/*
  1334. X * NAME
  1335. X *    func_getenv - get environment variables
  1336. X *
  1337. X * SYNOPSIS
  1338. X *    int func_getenv(wlist *result, wlist *args);
  1339. X *
  1340. X * DESCRIPTION
  1341. X *    Getenv is a built-in function of cook, described as follows:
  1342. X *    This function requires one or more arguments.
  1343. X *
  1344. X * RETURNS
  1345. X *    A word list containing the values of the environment variables
  1346. X *    given as arguments.
  1347. X *
  1348. X * CAVEAT
  1349. X *    The returned result is in dynamic memory.
  1350. X *    It is the responsibility of the caller to dispose of
  1351. X *    the result when it is finished, with a wl_free() call.
  1352. X */
  1353. X
  1354. Xstatic int func_getenv _((wlist *, wlist *));
  1355. X
  1356. Xstatic int
  1357. Xfunc_getenv(result, args)
  1358. X    wlist        *result;
  1359. X    wlist        *args;
  1360. X{
  1361. X    int        j;
  1362. X
  1363. X    assert(result);
  1364. X    assert(args);
  1365. X    assert(args->wl_nwords);
  1366. X    for (j = 1; j < args->wl_nwords; ++j)
  1367. X    {
  1368. X        char        *cp;
  1369. X        string_ty    *s;
  1370. X
  1371. X        cp = getenv(args->wl_word[j]->str_text);
  1372. X        if (!cp)
  1373. X            wl_append(result, str_false);
  1374. X        else
  1375. X        {
  1376. X            s = str_from_c(cp);
  1377. X            wl_append(result, s);
  1378. X            str_free(s);
  1379. X        }
  1380. X    }
  1381. X    return 0;
  1382. X}
  1383. X
  1384. X
  1385. X/*
  1386. X * NAME
  1387. X *    func_find_command - find pathname commands
  1388. X *
  1389. X * SYNOPSIS
  1390. X *    int func_find_command(wlist *result, wlist *args);
  1391. X *
  1392. X * DESCRIPTION
  1393. X *    Find_command is a built-in function of cook, described as follows:
  1394. X *    This function requires one or more arguments.
  1395. X *
  1396. X * RETURNS
  1397. X *    A word list containing the expanded pathname of the named commands
  1398. X *    given as arguments.
  1399. X *
  1400. X * CAVEAT
  1401. X *    The returned result is in dynamic memory.
  1402. X *    It is the responsibility of the caller to dispose of
  1403. X *    the result when it is finished, with a wl_free() call.
  1404. X */
  1405. X
  1406. Xstatic int func_find_command _((wlist *, wlist *));
  1407. X
  1408. Xstatic int
  1409. Xfunc_find_command(result, args)
  1410. X    wlist        *result;
  1411. X    wlist        *args;
  1412. X{
  1413. X    int        j;
  1414. X    string_ty    *paths;
  1415. X    char        *cp;
  1416. X
  1417. X    assert(result);
  1418. X    assert(args);
  1419. X    assert(args->wl_nwords);
  1420. X    cp = getenv("PATH");
  1421. X    if (!cp || !*cp)
  1422. X    {
  1423. X        expr_error
  1424. X        (
  1425. X            "%s: PATH environment variable not set",
  1426. X            args->wl_word[0]->str_text
  1427. X        );
  1428. X        return -1;
  1429. X    }
  1430. X    paths = str_from_c(cp);
  1431. X    for (j = 1; j < args->wl_nwords; ++j)
  1432. X    {
  1433. X        string_ty    *s;
  1434. X        string_ty    *s2;
  1435. X
  1436. X        s = args->wl_word[j];
  1437. X        if (strchr(s->str_text, '/'))
  1438. X        {
  1439. X            if (os_exists(s))
  1440. X            {
  1441. X                s2 = os_pathname(s);
  1442. X                wl_append(result, s2);
  1443. X                str_free(s2);
  1444. X            }
  1445. X            else
  1446. X                wl_append(result, str_false);
  1447. X        }
  1448. X        else
  1449. X        {
  1450. X            string_ty    *f;
  1451. X            int        n;
  1452. X
  1453. X            for (n = 0; ; ++n)
  1454. X            {
  1455. X                f = str_field(paths, ':', n);
  1456. X                if (!f)
  1457. X                {
  1458. X                    wl_append(result, str_false);
  1459. X                    break;
  1460. X                }
  1461. X                s2 = str_format("%S/%S", f, s);
  1462. X                str_free(f);
  1463. X                switch (os_exists(s2))
  1464. X                {
  1465. X                case -1:
  1466. X                    str_free(s2);
  1467. X                    return -1;
  1468. X
  1469. X                case 0:
  1470. X                    str_free(s2);
  1471. X                    continue;
  1472. X
  1473. X                case 1:
  1474. X                    f = os_pathname(s2);
  1475. X                    str_free(s2);
  1476. X                    wl_append(result, f);
  1477. X                    str_free(f);
  1478. X                    break;
  1479. X                }
  1480. X                break;
  1481. X            }
  1482. X        }
  1483. X    }
  1484. X    str_free(paths);
  1485. X    return 0;
  1486. X}
  1487. X
  1488. X
  1489. X/*
  1490. X * NAME
  1491. X *    func_collect - get output of a command
  1492. X *
  1493. X * SYNOPSIS
  1494. X *    int func_collect(wlist *result, wlist *args);
  1495. X *
  1496. X * DESCRIPTION
  1497. X *    Collect is a built-in function of cook, described as follows:
  1498. X *    This function requires one or more arguments.
  1499. X *
  1500. X * RETURNS
  1501. X *    A word list containing the values of the output lines of the
  1502. X *    program given in the arguments.
  1503. X *
  1504. X * CAVEAT
  1505. X *    The returned result is in dynamic memory.
  1506. X *    It is the responsibility of the caller to dispose of
  1507. X *    the result when it is finished, with a wl_free() call.
  1508. X */
  1509. X
  1510. Xstatic int func_collect _((wlist *, wlist *));
  1511. X
  1512. Xstatic int
  1513. Xfunc_collect(result, args)
  1514. X    wlist        *result;
  1515. X    wlist        *args;
  1516. X{
  1517. X    FILE        *fp;
  1518. X    string_ty    *s;
  1519. X    char        *delim;
  1520. X    int        status;
  1521. X
  1522. X    assert(result);
  1523. X    assert(args);
  1524. X    assert(args->wl_nwords);
  1525. X    if (args->wl_nwords < 2)
  1526. X    {
  1527. X        expr_error
  1528. X        (
  1529. X            "%s: requires one or more arguments",
  1530. X            args->wl_word[0]->str_text
  1531. X        );
  1532. X        return -1;
  1533. X    }
  1534. X    s = wl2str(args, 1, 32767);
  1535. X    option_set(OPTION_SILENT, OPTION_LEVEL_EXECUTE, 1);
  1536. X    option_set(OPTION_ERROK, OPTION_LEVEL_EXECUTE, 0);
  1537. X    if (!option_test(OPTION_SILENT))
  1538. X        expr_error("%s", s->str_text);
  1539. X    fp = popen(s->str_text, "r");
  1540. X    str_free(s);
  1541. X    if (!fp)
  1542. X    {
  1543. X        expr_error
  1544. X        (
  1545. X            "%s: %s",
  1546. X            args->wl_word[1]->str_text,
  1547. X            strerror(errno)
  1548. X        );
  1549. X        return -1;
  1550. X    }
  1551. X    delim = strchr(args->wl_word[0]->str_text, '_') ? "\n" : "\n \t\f";
  1552. X    for (;;)
  1553. X    {
  1554. X        char        buffer[1024];
  1555. X        char        *cp;
  1556. X        int        c;
  1557. X
  1558. X        for (;;)
  1559. X        {
  1560. X            c = fgetc(fp);
  1561. X            if (c == EOF || !strchr(delim, c))
  1562. X                break;
  1563. X        }
  1564. X        if (c == EOF)
  1565. X            break;
  1566. X        cp = buffer;
  1567. X        for (;;)
  1568. X        {
  1569. X            *cp++ = c;
  1570. X            c = fgetc(fp);
  1571. X            if (c == EOF || strchr(delim, c))
  1572. X                break;
  1573. X        }
  1574. X        s = str_n_from_c(buffer, cp - buffer);
  1575. X        wl_append(result, s);
  1576. X        str_free(s);
  1577. X        if (c == EOF)
  1578. X            break;
  1579. X    }
  1580. X    if (ferror(fp))
  1581. X    {
  1582. X        expr_error
  1583. X        (
  1584. X            "%s: %s",
  1585. X            args->wl_word[1]->str_text,
  1586. X            strerror(errno)
  1587. X        );
  1588. X        return -1;
  1589. X    }
  1590. X    status = pclose(fp);
  1591. X    status = exit_status(args->wl_word[0]->str_text, status);
  1592. X    if (status && !option_test(OPTION_ERROK))
  1593. X    {
  1594. X        option_undo_level(OPTION_LEVEL_EXECUTE);
  1595. X        return -1;
  1596. X    }
  1597. X    option_undo_level(OPTION_LEVEL_EXECUTE);
  1598. X    return 0;
  1599. X}
  1600. X
  1601. X
  1602. X/*
  1603. X * NAME
  1604. X *    func_opsys - describe operating system
  1605. X *
  1606. X * SYNOPSIS
  1607. X *    int func_opsys(wlist *result, wlist *args);
  1608. X *
  1609. X * DESCRIPTION
  1610. X *    Operating_system is a built-in function of cook, described as follows:
  1611. X *    This function must have zero or more arguments.
  1612. X *
  1613. X * RETURNS
  1614. X *    The resulting wordlist contains the values of various
  1615. X *    attributes of the operating system, as named in the arguments.
  1616. X *    If no attributes are named "name" is assumed.
  1617. X *
  1618. X * CAVEAT
  1619. X *    The returned result is in dynamic memory.
  1620. X *    It is the responsibility of the caller to dispose of
  1621. X *    the result when it is finished, with a wl_free() call.
  1622. X */
  1623. X
  1624. Xstatic int func_opsys _((wlist *, wlist *));
  1625. X
  1626. Xstatic int
  1627. Xfunc_opsys(result, args)
  1628. X    wlist        *result;
  1629. X    wlist        *args;
  1630. X{
  1631. X    int        j;
  1632. X    static string_ty    *name;
  1633. X    static string_ty    *machine;
  1634. X    static struct utsname uts;
  1635. X    static char    uts_defined;
  1636. X    static string_ty    *uts_system;
  1637. X    static string_ty    *uts_node;
  1638. X    static string_ty    *uts_release;
  1639. X    static string_ty    *uts_version;
  1640. X
  1641. X    if (!uts_defined)
  1642. X    {
  1643. X        uname(&uts);
  1644. X        uts_defined = 1;
  1645. X    }
  1646. X    if (!uts_system)
  1647. X        uts_system = str_from_c("system");
  1648. X    if (!uts_node)
  1649. X        uts_node = str_from_c("node");
  1650. X    if (!uts_release)
  1651. X        uts_release = str_from_c("release");
  1652. X    if (!uts_version)
  1653. X        uts_version = str_from_c("version");
  1654. X    if (!machine)
  1655. X        machine = str_from_c("machine");
  1656. X    if (!name)
  1657. X        name = str_from_c("name");
  1658. X    assert(result);
  1659. X    assert(args);
  1660. X    assert(args->wl_nwords);
  1661. X    if (args->wl_nwords < 2)
  1662. X        wl_append(args, name);
  1663. X    for (j = 1; j < args->wl_nwords; j++)
  1664. X    {
  1665. X        string_ty    *x;
  1666. X
  1667. X        x = args->wl_word[j];
  1668. X        if (str_equal(name, x))
  1669. X        {
  1670. X            static string_ty    *s;
  1671. X            if (!s)
  1672. X            {
  1673. X#if defined(sun) || defined(__sun__)
  1674. X                s = str_from_c("SunOS");
  1675. X#elif defined(unix) || defined(__unix__)
  1676. X                s = str_from_c("unix");
  1677. X#else
  1678. X                if (!s)
  1679. X                    fatal("what OS am I on?");
  1680. X#endif /* OSs */
  1681. X            }
  1682. X            wl_append(result, s);
  1683. X        }
  1684. X        else if (str_equal(uts_system, x))
  1685. X        {
  1686. X            static string_ty *s;
  1687. X            if (!s)
  1688. X                s = str_from_c(uts.sysname);
  1689. X            wl_append(result, s);
  1690. X        }
  1691. X        else if (str_equal(uts_node, x))
  1692. X        {
  1693. X            static string_ty *s;
  1694. X            if (!s)
  1695. X                s = str_from_c(uts.nodename);
  1696. X            wl_append(result, s);
  1697. X        }
  1698. X        else if (str_equal(uts_release, x))
  1699. X        {
  1700. X            static string_ty *s;
  1701. X            if (!s)
  1702. X                s = str_from_c(uts.release);
  1703. X            wl_append(result, s);
  1704. X        }
  1705. X        else if (str_equal(uts_version, x))
  1706. X        {
  1707. X            static string_ty *s;
  1708. X            if (!s)
  1709. X                s = str_from_c(uts.version);
  1710. X            wl_append(result, s);
  1711. X        }
  1712. X        else if (str_equal(machine, x))
  1713. X        {
  1714. X            static string_ty *s;
  1715. X            if (!s)
  1716. X                s = str_from_c(uts.machine);
  1717. X            wl_append(result, s);
  1718. X        }
  1719. X        else
  1720. X        {
  1721. X            expr_error
  1722. X            (
  1723. X                "%s: unknown \"%s\" attribute",
  1724. X                args->wl_word[0]->str_text,
  1725. X                x
  1726. X            );
  1727. X            return -1;
  1728. X        }
  1729. X    }
  1730. X    return 0;
  1731. X}
  1732. X
  1733. X
  1734. X#define STRINGSET_EOLN  1
  1735. X#define STRINGSET_WORD  2
  1736. X#define STRINGSET_MINUS 3
  1737. X#define STRINGSET_STAR  4
  1738. X
  1739. Xstatic wlist    stringset_args;
  1740. Xstatic size_t   stringset_pos;
  1741. Xstatic int      stringset_token;
  1742. Xstatic string_ty *stringset_token_value;
  1743. X
  1744. X
  1745. Xstatic void stringset_lex _((void));
  1746. X
  1747. Xstatic void
  1748. Xstringset_lex()
  1749. X{
  1750. X    static string_ty *minus;
  1751. X    static string_ty *star;
  1752. X
  1753. X    if (!minus)
  1754. X        minus = str_from_c("-");
  1755. X    if (!star)
  1756. X        star = str_from_c("*");
  1757. X    if (stringset_pos >= stringset_args.wl_nwords)
  1758. X    {
  1759. X        stringset_token_value = str_false;
  1760. X        stringset_token = STRINGSET_EOLN;
  1761. X        return;
  1762. X    }
  1763. X    stringset_token_value = stringset_args.wl_word[stringset_pos++];
  1764. X    if (str_equal(minus, stringset_token_value))
  1765. X    {
  1766. X        stringset_token = STRINGSET_MINUS;
  1767. X        return;
  1768. X    }
  1769. X    if (str_equal(star, stringset_token_value))
  1770. X    {
  1771. X        stringset_token = STRINGSET_STAR;
  1772. X        return;
  1773. X    }
  1774. X    stringset_token = STRINGSET_WORD;
  1775. X}
  1776. X
  1777. X
  1778. Xstatic int stringset_three _((wlist *));
  1779. X
  1780. Xstatic int
  1781. Xstringset_three(result)
  1782. X    wlist        *result;
  1783. X{
  1784. X    while (stringset_token == STRINGSET_WORD)
  1785. X    {
  1786. X        wl_append_unique(result, stringset_token_value);
  1787. X        stringset_lex();
  1788. X    }
  1789. X    return 0;
  1790. X}
  1791. X
  1792. X
  1793. Xstatic int stringset_two _((wlist *));
  1794. X
  1795. Xstatic int
  1796. Xstringset_two(result)
  1797. X    wlist        *result;
  1798. X{
  1799. X    if (stringset_three(result))
  1800. X        return -1;
  1801. X    while (stringset_token == STRINGSET_STAR)
  1802. X    {
  1803. X        wlist        lhs;
  1804. X        wlist        rhs;
  1805. X        int        j;
  1806. X        string_ty    *s;
  1807. X
  1808. X        stringset_lex();
  1809. X        wl_zero(&rhs);
  1810. X        if (stringset_three(&rhs))
  1811. X            return -1;
  1812. X        lhs = *result;
  1813. X        wl_zero(result);
  1814. X        for (j = 0; j < rhs.wl_nwords; ++j)
  1815. X        {
  1816. X            s = rhs.wl_word[j];
  1817. X            if (wl_member(&lhs, s))
  1818. X                wl_append_unique(result, s);
  1819. X        }
  1820. X        wl_free(&lhs);
  1821. X        wl_free(&rhs);
  1822. X    }
  1823. X    return 0;
  1824. X}
  1825. X
  1826. X
  1827. Xstatic int stringset_one _((wlist *));
  1828. X
  1829. Xstatic int
  1830. Xstringset_one(result)
  1831. X    wlist        *result;
  1832. X{
  1833. X    if (stringset_two(result))
  1834. X        return -1;
  1835. X    while (stringset_token == STRINGSET_MINUS)
  1836. X    {
  1837. X        wlist        wl;
  1838. X        int        j;
  1839. X
  1840. X        wl_zero(&wl);
  1841. X        stringset_lex();
  1842. X        if (stringset_two(&wl))
  1843. X            return -1;
  1844. X        for (j = 0; j < wl.wl_nwords; ++j)
  1845. X            wl_delete(result, wl.wl_word[j]);
  1846. X        wl_free(&wl);
  1847. X    }
  1848. X    return 0;
  1849. X}
  1850. X
  1851. X
  1852. Xstatic int stringset _((wlist *, wlist *));
  1853. X
  1854. Xstatic int
  1855. Xstringset(result, args)
  1856. X    wlist        *result;
  1857. X    wlist        *args;
  1858. X{
  1859. X    wlist        wl;
  1860. X    int        j;
  1861. X
  1862. X    stringset_args = *args;
  1863. X    stringset_pos = 1;
  1864. X    stringset_lex();
  1865. X
  1866. X    wl_zero(&wl);
  1867. X    if (stringset_one(&wl))
  1868. X        return -1;
  1869. X    for (j = 0; j < wl.wl_nwords; ++j)
  1870. X        wl_append(result, wl.wl_word[j]);
  1871. X    wl_free(&wl);
  1872. X    return 0;
  1873. X}
  1874. X
  1875. X
  1876. X/*
  1877. X * NAME
  1878. X *    func_quote - quote the arguments
  1879. X *
  1880. X * SYNOPSIS
  1881. X *    int func_quote(wlist *result, wlist *args);
  1882. X *
  1883. X * DESCRIPTION
  1884. X *    The quote function is a built-in of cook, described as follows:
  1885. X *    This function requires one or more arguments.
  1886. X *
  1887. X * RETURNS
  1888. X *    A word list containing the values of the arguments
  1889. X *    surrounded by double quotes.
  1890. X *
  1891. X * CAVEAT
  1892. X *    The returned result is in dynamic memory.
  1893. X *    It is the responsibility of the caller to dispose of
  1894. X *    the result when it is finished, with a wl_free() call.
  1895. X */
  1896. X
  1897. Xstatic int func_quote _((wlist *, wlist *));
  1898. X
  1899. Xstatic int
  1900. Xfunc_quote(result, args)
  1901. X    wlist        *result;
  1902. X    wlist        *args;
  1903. X{
  1904. X    int        j;
  1905. X    static char    *tmp;
  1906. X    static size_t    tmp_len;
  1907. X    size_t        len;
  1908. X    char        *cp1;
  1909. X    char        *cp2;
  1910. X    char        *cp3;
  1911. X    string_ty    *s;
  1912. X    static char    special[] = "\bb\ff\nn\rr\tt";
  1913. X
  1914. X    assert(result);
  1915. X    assert(args);
  1916. X    assert(args->wl_nwords);
  1917. X    for (j = 1; j < args->wl_nwords; ++j)
  1918. X    {
  1919. X        len = 2;
  1920. X        for (cp1 = args->wl_word[j]->str_text; *cp1; ++cp1)
  1921. X        {
  1922. X            if (*cp1 < ' ' || *cp1 > '~')
  1923. X            {
  1924. X                if (strchr(special, *cp1))
  1925. X                    len += 2;
  1926. X                else
  1927. X                    len += 4;
  1928. X            }
  1929. X            else
  1930. X            {
  1931. X                if (strchr("\"\\", *cp1))
  1932. X                    ++len;
  1933. X                ++len;
  1934. X            }
  1935. X        }
  1936. X        if (len > tmp_len)
  1937. X        {
  1938. X            tmp_len = len;
  1939. X            if (!tmp)
  1940. X                tmp = mem_alloc(tmp_len);
  1941. X            else
  1942. X                mem_change_size(&tmp, tmp_len);
  1943. X        }
  1944. X        cp2 = tmp;
  1945. X        *cp2++ = '"';
  1946. X        for (cp1 = args->wl_word[j]->str_text; *cp1; ++cp1)
  1947. X        {
  1948. X            if (*cp1 < ' ' || *cp1 > '~')
  1949. X            {
  1950. X                cp3 = strchr(special, *cp1);
  1951. X                if (cp3)
  1952. X                {
  1953. X                    *cp2++ = '\\';
  1954. X                    *cp2++= cp3[1];
  1955. X                }
  1956. X                else
  1957. X                {
  1958. X                    *cp2++ = '\\';
  1959. X                    *cp2++ = '0' + ((*cp1 >> 6) & 3);
  1960. X                    *cp2++ = '0' + ((*cp1 >> 3) & 7);
  1961. X                    *cp2++ = '0' + (*cp1 & 7);
  1962. X                }
  1963. X            }
  1964. X            else
  1965. X            {
  1966. X                if (strchr("\"\\", *cp1))
  1967. X                    *cp2++ = '\\';
  1968. X                *cp2++ = *cp1;
  1969. X            }
  1970. X        }
  1971. X        *cp2 = '"';
  1972. X        s = str_n_from_c(tmp, len);
  1973. X        wl_append(result, s);
  1974. X        str_free(s);
  1975. X    }
  1976. X    return 0;
  1977. X}
  1978. X
  1979. X
  1980. X/*
  1981. X * NAME
  1982. X *    func_uptodate - test if files are up to date
  1983. X *
  1984. X * SYNOPSIS
  1985. X *    int func_uptodate(wlist *result, wlist *args);
  1986. X *
  1987. X * DESCRIPTION
  1988. X *    The uptodate function is a built-in of cook, described as follows:
  1989. X *    returns true if all the arguments are up-to-date.
  1990. X *    Does not build them if they are not.
  1991. X *    This function requires one or more arguments.
  1992. X *
  1993. X * RETURNS
  1994. X *    A word list containing true ("1") if all arguments are up-to-date,
  1995. X *    or false ("") if one or more could not.
  1996. X *
  1997. X * CAVEAT
  1998. X *    The returned result is in dynamic memory.
  1999. X *    It is the responsibility of the caller to dispose of
  2000. X *    the result when it is finished, with a wl_free() call.
  2001. X */
  2002. X
  2003. Xstatic int func_uptodate _((wlist *, wlist *));
  2004. X
  2005. Xstatic int
  2006. Xfunc_uptodate(result, args)
  2007. X    wlist        *result;
  2008. X    wlist        *args;
  2009. X{
  2010. X    int        j;
  2011. X    int        ret;
  2012. X
  2013. X    assert(result);
  2014. X    assert(args);
  2015. X    assert(args->wl_nwords);
  2016. X    for (j = 1; j < args->wl_nwords; ++j)
  2017. X    {
  2018. X        ret = isit_uptodate(args->wl_word[j]);
  2019. X        if (ret < 0)
  2020. X            return -1;
  2021. X        if (!ret)
  2022. X        {
  2023. X            wl_append(result, str_false);
  2024. X            return 0;
  2025. X        }
  2026. X    }
  2027. X    wl_append(result, str_true);
  2028. X    return 0;
  2029. X}
  2030. X
  2031. X
  2032. X/*
  2033. X * NAME
  2034. X *    func_cando - test if know how to cook given files
  2035. X *
  2036. X * SYNOPSIS
  2037. X *    int func_cando(wlist *result, wlist *args);
  2038. X *
  2039. X * DESCRIPTION
  2040. X *    The cando function is a built-in of cook, described as follows:
  2041. X *    returns true if all the arguments are known how to be cooked.
  2042. X *    This function requires one or more arguments.
  2043. X *
  2044. X * RETURNS
  2045. X *    A word list containing true ("1") if can do all arguments,
  2046. X *    or false ("") if one or more could not.
  2047. X *
  2048. X * CAVEAT
  2049. X *    The returned result is in dynamic memory.
  2050. X *    It is the responsibility of the caller to dispose of
  2051. X *    the result when it is finished, with a wl_free() call.
  2052. X */
  2053. X
  2054. Xstatic int func_cando _((wlist *, wlist *));
  2055. X
  2056. Xstatic int
  2057. Xfunc_cando(result, args)
  2058. X    wlist        *result;
  2059. X    wlist        *args;
  2060. X{
  2061. X    int        j;
  2062. X    int        ret;
  2063. X
  2064. X    assert(result);
  2065. X    assert(args);
  2066. X    assert(args->wl_nwords);
  2067. X    for (j = 1; j < args->wl_nwords; ++j)
  2068. X    {
  2069. X        ret = cando(args->wl_word[j]);
  2070. X        if (!ret)
  2071. X        {
  2072. X            wl_append(result, str_false);
  2073. X            return 0;
  2074. X        }
  2075. X    }
  2076. X    wl_append(result, str_true);
  2077. X    return 0;
  2078. X}
  2079. X
  2080. X
  2081. X/*
  2082. X * NAME
  2083. X *    func_sort - sort the arguments
  2084. X *
  2085. X * SYNOPSIS
  2086. X *    int func_sort(wlist *result, wlist *args);
  2087. X *
  2088. X * DESCRIPTION
  2089. X *    The func_sort function is a built-in of cook, described as follows:
  2090. X *    sorts the arguments lexicagraphically.
  2091. X *    This function requires zero or more arguments.
  2092. X *
  2093. X * RETURNS
  2094. X *    A sorted word list.
  2095. X *
  2096. X * CAVEAT
  2097. X *    The returned result is in dynamic memory.
  2098. X *    It is the responsibility of the caller to dispose of
  2099. X *    the result when it is finished, with a wl_free() call.
  2100. X */
  2101. X
  2102. Xstatic int func_sort_cmp _((const void *, const void *));
  2103. X
  2104. Xstatic int
  2105. Xfunc_sort_cmp(va, vb)
  2106. X    const void    *va;
  2107. X    const void    *vb;
  2108. X{
  2109. X    string_ty    *a;
  2110. X    string_ty    *b;
  2111. X
  2112. X    a = *(string_ty **)va;
  2113. X    b = *(string_ty **)vb;
  2114. X    return strcmp(a->str_text, b->str_text);
  2115. X}
  2116. X
  2117. X
  2118. Xstatic int func_sort _((wlist *, wlist *));
  2119. X
  2120. Xstatic int
  2121. Xfunc_sort(result, args)
  2122. X    wlist        *result;
  2123. X    wlist        *args;
  2124. X{
  2125. X    int        j;
  2126. X    int        start;
  2127. X
  2128. X    assert(result);
  2129. X    assert(args);
  2130. X    switch (args->wl_nwords)
  2131. X    {
  2132. X    case 0:
  2133. X        assert(0);
  2134. X
  2135. X    case 1:
  2136. X        return 0;
  2137. X
  2138. X    case 2:
  2139. X        wl_append(result, args->wl_word[1]);
  2140. X        return 0;
  2141. X    }
  2142. X    start = result->wl_nwords;
  2143. X    for (j = 1; j < args->wl_nwords; ++j)
  2144. X        wl_append(result, args->wl_word[j]);
  2145. X    qsort
  2146. X    (
  2147. X        &result->wl_word[start],
  2148. X        args->wl_nwords - 1,
  2149. X        sizeof(result->wl_word[0]),
  2150. X        func_sort_cmp
  2151. X    );
  2152. X    return 0;
  2153. X}
  2154. X
  2155. X
  2156. X/*
  2157. X * NAME
  2158. X *    func - table of built-in functions
  2159. X *
  2160. X * SYNOPSIS
  2161. X *    func_ty func[];
  2162. X *
  2163. X * DESCRIPTION
  2164. X *    Func is a table of function names and pointers
  2165. X *    for the built-in functions of cook.
  2166. X */
  2167. X
  2168. Xstatic    func_ty func[] =
  2169. X{
  2170. X    { "and",        func_and,        },
  2171. X    { "cando",        func_cando,        },
  2172. X    { "catenate",        func_catenate,        },
  2173. X    { "collect",        func_collect,        },
  2174. X    { "collect_lines",    func_collect,        },
  2175. X    { "count",        func_count,        },
  2176. X    { "defined",        func_defined,        },
  2177. X    { "dir",        func_dir,        },
  2178. X    { "dirname",        func_dir,        },
  2179. X    { "downcase",        func_downcase,        },
  2180. X    { "entryname",        func_entryname,        },
  2181. X    { "execute",        func_exec,        },
  2182. X    { "exists",        func_mtime,        },
  2183. X    { "find_command",    func_find_command,    },
  2184. X    { "fromto",        func_fromto,        },
  2185. X    { "getenv",        func_getenv,        },
  2186. X    { "glob",        glob,            },
  2187. X    { "head",        func_head,        },
  2188. X    { "if",            func_if,        },
  2189. X    { "in",            func_in,        },
  2190. X    { "match",        func_match,        },
  2191. X    { "matches",        func_match,        },
  2192. X    { "match_mask",        func_match_mask,    },
  2193. X    { "mtime",        func_mtime,        },
  2194. X    { "not",        func_not,        },
  2195. X    { "operating_system",    func_opsys,        },
  2196. X    { "os",            func_opsys,        },
  2197. X    { "or",            func_or,        },
  2198. X    { "pathname",        func_pathname,        },
  2199. X    { "prepost",        func_prepost,        },
  2200. X    { "quote",        func_quote,        },
  2201. X    { "resolve",        cook_mtime_resolve,    },
  2202. X    { "sort",        func_sort,        },
  2203. X    { "stringset",        stringset,        },
  2204. X    { "tail",        func_tail,        },
  2205. X    { "upcase",        func_upcase,        },
  2206. X    { "uptodate",        func_uptodate,        },
  2207. X};
  2208. X
  2209. X
  2210. X/*
  2211. X * NAME
  2212. X *    builtin_initialize - start up builtins
  2213. X *
  2214. X * SYNOPSIS
  2215. X *    void builtin_initialize(void);
  2216. X *
  2217. X * DESCRIPTION
  2218. X *    The builtin_initialize function is used to initialize the symbol table
  2219. X *    with the names and pointers to the builtin functions.
  2220. X *
  2221. X * CAVEAT
  2222. X *    This function must be called after the id_initialize function.
  2223. X */
  2224. X
  2225. Xvoid
  2226. Xbuiltin_initialize()
  2227. X{
  2228. X    func_ty        *fp;
  2229. X    string_ty    *s;
  2230. X
  2231. X    for (fp = func; fp < ENDOF(func); ++fp)
  2232. X    {
  2233. X        s = str_from_c(fp->f_name);
  2234. X        id_assign(s, ID_CLASS_BUILTIN, fp->f_code);
  2235. X        str_free(s);
  2236. X    }
  2237. X}
  2238. END_OF_FILE
  2239. if test 43130 -ne `wc -c <'cook/builtin.c'`; then
  2240.     echo shar: \"'cook/builtin.c'\" unpacked with wrong size!
  2241. fi
  2242. # end of 'cook/builtin.c'
  2243. fi
  2244. echo shar: End of archive 11 \(of 11\).
  2245. cp /dev/null ark11isdone
  2246. MISSING=""
  2247. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  2248.     if test ! -f ark${I}isdone ; then
  2249.     MISSING="${MISSING} ${I}"
  2250.     fi
  2251. done
  2252. if test "${MISSING}" = "" ; then
  2253.     echo You have unpacked all 11 archives.
  2254.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2255. else
  2256.     echo You still need to unpack the following archives:
  2257.     echo "        " ${MISSING}
  2258. fi
  2259. ##  End of shell archive.
  2260. exit 0
  2261.